﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using YasharEl.Infrastructure.ApplicationModel.Bootstrap.Extensibility;
using System.Linq.Expressions;
using System.Diagnostics.Contracts;
using System.Globalization;

namespace YasharEl.Infrastructure.ApplicationModel.Bootstrap.Behavior
{
    /// <summary>
    /// The lazy behavior is responsible for creating a behavior at the time of the behave call.
    /// </summary>
    /// <typeparam name="TExtension">The type of the extension.</typeparam>
    public class LazyBehavior<TExtension> : IBehavior<TExtension>
        where TExtension : IBootstrappingExtension
    {
        private readonly Func<IBehavior<TExtension>> behaviorProvider;
        private readonly Expression<Func<IBehavior<TExtension>>> behaviorProviderExpression;

        /// <summary>
        /// Initializes a new instance of the <see cref="LazyBehavior&lt;TExtension&gt;"/> class.
        /// </summary>
        /// <param name="behaviorProvider">The behavior provider.</param>
        public LazyBehavior(Expression<Func<IBehavior<TExtension>>> behaviorProvider)
        {
            Contract.Requires<ArgumentNullException>(behaviorProvider != null, "behaviorProvider could not be null.");

            this.behaviorProviderExpression = behaviorProvider;
            this.behaviorProvider = this.behaviorProviderExpression.Compile();
        }

        public string Name
        {
            get
            {
                return this.GetType().FullNameToString();
            }
        }

        /// <remarks>Creates the behavior with the specified behavior provider and executes behave on the lazy initialized behavior.</remarks>
        public void Behave(IEnumerable<TExtension> extensions)
        {
            IBehavior<TExtension> behavior = this.behaviorProvider();

            behavior.Behave(extensions);
        }

        public string Describe()
        {
            return string.Format(
                CultureInfo.InvariantCulture, "Creates the behavior with {0} and executes behave on the lazy initialized behavior.", this.behaviorProviderExpression);
        }
    }
}
